﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using wne.Context;
using wne.core;
using wne.core.Interface;
using wne.models;
using Wne.SenderService.GlobalStorage;

namespace Wne.SenderService
{
    public class IssueManager
    {
        private string _filePath = "";
        private DocumentFacade _documentFacade;
        private IssueSemaphore _semaphore;

        public IssueManager()
        {
            _documentFacade = new DocumentFacadeSql();
        }
        public void TryIssue(IssueSemaphore semaphore)
        {
            var threadId = Guid.NewGuid();
            lock (semaphore)
            {
                _semaphore = semaphore;
            }
            using (var context = new tpksEntities())
            {
                var tryList = context.ShedulerDocs.Where(x => x.Status == (short)DocStatus.Created).ToList();
                foreach (var shedulerDoc in tryList)
                {
                    context.Database.ExecuteSqlCommand("Update ShedulerDocs Set ProcessId = {0}, Status = {1} where TimeStamp={2}",
                        threadId.ToString(),(short)DocStatus.InProcess, BitConverter.ToInt64(shedulerDoc.TimeStamp.Reverse().ToArray(), 0));
                    var order = context.ShedulerDocs.FirstOrDefault(x => x.ProcessId == threadId.ToString());
                    if (order != null)
                    {
                        DoIssue(order.UniqueId);
                        return;
                    }
                }
            }
            //Берем список заказов
            //var orderLineRepository = _repositoryFactory.GetOrderLineRepository();
            //var tryList = orderLineRepository.GetOrderLinesTop(20);
            //foreach (var order in tryList)
            //{
            //    var newItem = orderLineRepository.TryLockedOrder(new Guid(), order);
            //    if (newItem != null)
            //        return IssueKeysForOrder(newItem);
            //}
            //return IssuerResult.Failed;
        }

        private string GetXml(object doc)
        {
            var ser = new XmlSerializer(doc.GetType());
            var q = new StringWriter();
            ser.Serialize(q, doc);
            return q.ToString();
        }

        private byte[] GetFile(string name)
        {
            return System.IO.File.ReadAllBytes(name);
        }
        public void DoIssue(Guid idDoc)
        {
            using (var context = new tpksEntities())
            {

                if (context.ShedulerDocs.FirstOrDefault(x => x.UniqueId == idDoc).IsForSend == 0)
                    SendDocument(idDoc);
                else
                    GiveDocument(idDoc);
                //var fullDocModel = (new DocumentFacadeSql()).GetFullDoc(shedulerDoc.Doc_ID);
                //var request = new DocumentResponse
                //{
                //    Document = GetXml(fullDocModel),
                //    AuthorEmail = shedulerDoc.User.Email,
                //    Id = shedulerDoc.UniqueId
                //};
                //client.AddDocument(request);
            }
        }
        private void GiveDocument(Guid idDoc)
        {
            var context = new tpksEntities();
            var shedulerDoc =
                    context.ShedulerDocs.Include("User").Include("ShedulerFiles").FirstOrDefault(x => x.UniqueId == idDoc);
            var client = new GlobalWcfClient();
            //Получаем файлы
            while (shedulerDoc.ShedulerFiles.Any(x => x.AttachmentStatus == 0))
            {
                //Пока дают
                lock (_semaphore)
                {
                    if (!_semaphore.GreenLight)
                        return;
                }
                var attach= shedulerDoc.ShedulerFiles.FirstOrDefault(x => x.AttachmentStatus == 0);
                var file = client.GetAttachment(attach.UniqueAttachmentId, shedulerDoc.Password);
                _documentFacade.SaveFileToDoc(shedulerDoc.Doc_ID, file.File, file.Name);
                attach.AttachmentStatus = 1;
                context.SaveChanges();
            }
            shedulerDoc.Status = (short)DocStatus.Success;
            context.SaveChanges();
            context.Dispose();
        }

        private void SendDocument(Guid shedulerDocId)
        {
            var context = new tpksEntities();
            var shedulerDoc =
                    context.ShedulerDocs.Include("User").Include("ShedulerFiles").FirstOrDefault(x => x.UniqueId == shedulerDocId);
            var client = new GlobalWcfClient();
            //Смотрим, надо ли добавлять документ
            if (shedulerDoc.ShedulerFiles.All(x => x.AttachmentStatus == 0))
            {
               var fullDocModel = (new DocumentFacadeSql()).GetFullDoc(shedulerDoc.Doc_ID);
                var toSend = new DocumentResponse
                {
                    Document = GetXml(fullDocModel),
                    AuthorEmail = shedulerDoc.User.Email,
                    Id = shedulerDoc.UniqueId,
                    AttachmentsGuid = shedulerDoc.ShedulerFiles.Select(x => x.UniqueAttachmentId).ToArray()
                };
                client.AddDocument(toSend);
            }
            //Отправляем файлы
            while (shedulerDoc.ShedulerFiles.Any(x => x.AttachmentStatus == 0))
            {
                //Пока дают
                lock (_semaphore)
                {
                    if (!_semaphore.GreenLight)
                        return;
                }
                var attach = shedulerDoc.ShedulerFiles.FirstOrDefault(x => x.AttachmentStatus == 0);
                client.AddAttachmentToDocument(new AttachmentResponse
                {
                    Name = attach.Name,
                    File = GetFile(attach.Name)
                },shedulerDoc.UniqueId);
                attach.AttachmentStatus = 1;
                context.SaveChanges();
            }
            client.FinishUploadDocument(shedulerDocId);
            shedulerDoc.Status = (short)DocStatus.Success;
            context.SaveChanges();
            context.Dispose();
        }
    }


}
